package vn.edu.fpt.xml.back.services.news;

import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.RuntimeConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import vn.edu.fpt.xml.back.config.XnConfiguration;
import vn.edu.fpt.xml.back.daos.ArticleDao;
import vn.edu.fpt.xml.back.daos.ChannelDao;
import vn.edu.fpt.xml.back.dtos.news.ArticleEntities;
import vn.edu.fpt.xml.back.dtos.news.Channel;
import vn.edu.fpt.xml.back.dtos.news.Item;
import vn.edu.fpt.xml.back.dtos.news.Rss;
import vn.edu.fpt.xml.back.entities.ArticleEntity;
import vn.edu.fpt.xml.back.entities.ChannelEntity;
import vn.edu.fpt.xml.back.utils.DateUtils;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.*;

/**
 * Created by hiephn on 2014/04/29.
 */
@Component
public class NewsProviderService {

    protected static final Logger LOGGER = LoggerFactory.getLogger(NewsProviderService.class);

    @Resource(name = "articleDao")
    protected ArticleDao articleDao;
    @Resource(name = "channelDao")
    protected ChannelDao channelDao;
    @Resource(name = "dateUtils")
    protected DateUtils dateUtils;
    @Resource(name = "xnConfiguration")
    protected XnConfiguration xnConfiguration;

    @Transactional
    public void persistArticle(ArticleEntities articleEntities) {
        articleDao.deleteAll();
        for (ArticleEntity articleEntity : articleEntities.getArticleEntityList()) {
            String channelTitle = articleEntity.getChannelTitle();
            ChannelEntity channelEntity = channelDao.findByTitle(channelTitle);

            // Init the channel if it is null
            if  (channelEntity == null) {
                channelEntity = new ChannelEntity();
                channelEntity.setTitle(channelTitle);
                channelDao.save(channelEntity);
            }

            try {
                Timestamp publicDate = dateUtils.toTimestamp(articleEntity.getPublicDateString(), DateUtils.RSS_TIMESTAMP_PATTERN);
                Object obj = articleDao.findByTitleAndPubicDate(articleEntity.getTitle(), publicDate);

                if (obj == null) {
                    articleEntity.setPublicDate(publicDate);
                    articleEntity.setChannelId(channelEntity.getId());
                    articleEntity.setChannelByChannelId(channelEntity);
                    articleDao.save(articleEntity);
                }
            } catch (ParseException e) {
                LOGGER.error(String.format("Ignore the item because unable to parse item (article) public date: %s. Expected date pattern: %s", articleEntity.getPublicDateString(), DateUtils.RSS_TIMESTAMP_PATTERN), e);
            }
        }
    }

    public List<String> getChannelList() {
        List<ChannelEntity> channelEntityList = channelDao.findAll();
        List<String> channelList = new ArrayList<String>(channelEntityList.size());

        for (ChannelEntity channelEntity : channelEntityList) {
            channelList.add(channelEntity.getTitle());
        }

        return channelList;
    }

    public Map generateHomePageContent() {

        List<ArticleEntity> articleEntityList = articleDao.findArticleOnHomePage();
        if (articleEntityList == null || articleEntityList.size() == 0) {
            return null;
        }

        /**
         * Velocity object structure:
         * ChannelList {(
         *     channelMap {
         *          "title" : "lsdjfier"
         *          "articleList" : ArticleList {(
         *                              articleMap {
         *                                  "title" : "sldfjijoit"
         *                                  "image" : "sldfjie"
         *                                  "description" : "lkdjfidf"
         *                                  "symbolLink" : "sldjfie"
         *                                  "time" : "sldkfji"
         *                                  "date" : "lsjiet"
         *                              })
         *                           }
         *     }
         * )}
         */
        List channelList = new ArrayList();
        Map channelMap = new HashMap();
        List<Map<String, String>> articleList = new ArrayList<Map<String, String>>();
        Map<String, String> articleMap = null;
        String currentChannelTitle = articleEntityList.get(0).getChannelByChannelId().getTitle();
        for (ArticleEntity articleEntity : articleEntityList) {
            if (!StringUtils.equals(currentChannelTitle, articleEntity.getChannelByChannelId().getTitle())) {
                // finalize last loop
                channelMap.put("title", currentChannelTitle);
                channelMap.put("articleList", articleList);
                channelList.add(channelMap);

                // init new loop
                channelMap = new HashMap();
                articleList = new ArrayList<Map<String, String>>();

                currentChannelTitle = articleEntity.getChannelByChannelId().getTitle();
            }

            String dateTime = dateUtils.toString(articleEntity.getPublicDate(), DateUtils.XN_CLOUD_DATETIME_SIMPLE_FORMAT_FOR_DISPLAY_PATTERN);

            articleMap = new HashMap<String, String>();
            articleMap.put("title", articleEntity.getTitle());
            articleMap.put("description", articleEntity.getDescription());
            articleMap.put("image", articleEntity.getImage());
            articleMap.put("symbolicLink", StringUtils.substring(articleEntity.getOriginUrl(), StringUtils.indexOf(articleEntity.getOriginUrl(), "vnexpress.net") + "vnexpress.net".length()));
            articleMap.put("time", StringUtils.substring(dateTime, 0, 6));
            articleMap.put("date", StringUtils.substring(dateTime, 6));
            articleList.add(articleMap);
        }
        channelMap.put("title", currentChannelTitle);
        channelMap.put("articleList", articleList);
        channelList.add(channelMap);

        Properties properties = new Properties();
        properties.setProperty(RuntimeConstants.INPUT_ENCODING, "UTF-8");
        properties.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8");
        properties.setProperty("string.resource.loader.encoding", "UTF-8");
        Velocity.init(properties);
        VelocityContext context = new VelocityContext();
        context.put("channelList", channelList);
        StringWriter writer = new StringWriter();

        Velocity.evaluate(context, writer, "homePageContent", xnConfiguration.getXnCloudFrontHomepageContentHtml());
        String homePageContent = writer.toString();

        Map<String, String> responseMap = new HashMap<String, String>(1);
        responseMap.put("homePageContent", homePageContent);
        return responseMap;
    }

    public ArticleEntity getArticleBySymbolicLink(String symbolicLink) {
        ArticleEntity articleEntity = articleDao.findArticleByRelativeOriginUrl(symbolicLink);
        articleDao.detach(articleEntity);

        String simpleFormatDate = dateUtils.toString(articleEntity.getPublicDate(), DateUtils.XN_CLOUD_DATETIME_SIMPLE_FORMAT_FOR_DISPLAY_PATTERN);
        articleEntity.setPublicDateString(simpleFormatDate);

        return articleEntity;
    }
}
